﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Waiter.Common;
using DevComponents.DotNetBar.Controls;
using Waiter.DataLayer;

namespace Waiter.Controler
{
    class SalaryCtrl
    {
        /// <summary>
        /// Xóa đi lương đã được tính (trước khi tính lương lại)
        /// </summary>
        /// <param name="pMonthToPay">Tháng tính lương</param>
        /// <param name="strStaffCode">Code nhân viên cần tính lương (nếu là string.empty thì sẽ tính lương của toàn bộ nhân viên)</param>
        /// <returns></returns>
        public string fsDeleteSalary(bool pIsFirst, DateTime pMonthToPay, string strStaffCode)
        {
            int nMidDay;
            DateTime dateFirstDayInMonth;
            DateTime dateLastDayInMonth;
            List<SALARY> myListSalaryDelete = new List<SALARY>();
            SALARY_CHANGE mySalaryChangeDelete = new SALARY_CHANGE();

            try//Tính toán các thông tin init
            {
                //Lấy thời điểm tính lương
                MASTER myMaster = CommonGlobalVariable.globalDataContext.MASTERs.SingleOrDefault(x => x.GROUP_CODE == CommonConstants.NGAY_GIUA_THANG & x.DEL_FLG == false);
                if (myMaster == null)
                {
                    throw new Exception();
                }

                nMidDay = Convert.ToInt32(myMaster.VALUE);//Ngày giữa tháng            

                if (pIsFirst == true)
                {
                    //Ngày, giờ bắt đầu tháng
                    dateFirstDayInMonth = new DateTime(pMonthToPay.Year, pMonthToPay.Month, 1, 0, 0, 0);
                    //Ngày giờ kết thúc tháng
                    dateLastDayInMonth = new DateTime(pMonthToPay.Year, pMonthToPay.Month, nMidDay, 23, 59, 59);
                }
                else
                {
                    //Ngày, giờ giữa tháng
                    dateFirstDayInMonth = new DateTime(pMonthToPay.Year, pMonthToPay.Month, nMidDay + 1, 0, 0, 0);
                    //Ngày giờ kết thúc tháng
                    dateLastDayInMonth = new DateTime(pMonthToPay.Year, pMonthToPay.Month, DateTime.DaysInMonth(pMonthToPay.Year, pMonthToPay.Month), 23, 59, 59);
                }
            }
            catch (Exception ex)
            {
                CommonLogging.fsWriteLog(CommonConstants.LOG_TYPE_ERROR,
                           "SalaryCtrl.fsDeleteSalary Tính toán các thông tin init",
                           CommonUtils.fsParamListToString(new object[3] { pIsFirst, pMonthToPay, strStaffCode }),
                           ex.ToString());
                return "Cài đặt ngày giữa tháng không đúng! Không thể tiến hành tính toán. Xin hãy kiểm tra lại.";
            }

            /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

            try//Bắt đầu delete tiền lương
            {
                if (strStaffCode == string.Empty)//Xóa thông tin lương đã tính (trong tháng) của tất cả nhân viên
                {
                    //Load thông tin cần xóa tại table SALARY
                    myListSalaryDelete = CommonGlobalVariable.globalDataContext.SALARies.Where(x => x.MONTH_OUTPUT >= dateFirstDayInMonth & x.MONTH_OUTPUT <= dateLastDayInMonth).ToList();

                    //Xóa thông tin tại table SALARY_CHANGE
                    if (myListSalaryDelete != null && myListSalaryDelete.Count > 0)
                    {
                        foreach (var item in myListSalaryDelete)
                        {
                            mySalaryChangeDelete = CommonGlobalVariable.globalDataContext.SALARY_CHANGEs.SingleOrDefault(x => x.SALARY_CODE == item.CODE);
                            if (mySalaryChangeDelete != null && mySalaryChangeDelete.CODE != string.Empty)
                            {
                                CommonGlobalVariable.globalDataContext.SALARY_CHANGEs.DeleteOnSubmit(mySalaryChangeDelete);//Đánh dấu xóa
                            }
                        }

                        CommonGlobalVariable.globalDataContext.SubmitChanges();//Xóa data

                        //Xóa thông tin tại table SALARY
                        foreach (SALARY item in myListSalaryDelete)
                        {
                            CommonGlobalVariable.globalDataContext.SALARies.DeleteOnSubmit(item);//Đánh dấu xóa
                        }
                        CommonGlobalVariable.globalDataContext.SubmitChanges();//Xóa data

                        return "Đã xóa thành công";
                    }
                    else
                    {
                        return "Không tìm thấy thông tin lương cần xóa";
                    }
                }
                else//Xóa thông tin lương đã tính (trong tháng) của nhân viên được chọn
                {
                    //Load thông tin cần xóa tại table SALARY
                    myListSalaryDelete = CommonGlobalVariable.globalDataContext.SALARies.Where(x => x.MONTH_OUTPUT == pMonthToPay & x.STAFF_CODE == strStaffCode).ToList();

                    //Xóa thông tin tại table SALARY_CHANGE
                    if (myListSalaryDelete != null && myListSalaryDelete.Count > 0)
                    {
                        foreach (var item in myListSalaryDelete)
                        {
                            mySalaryChangeDelete = CommonGlobalVariable.globalDataContext.SALARY_CHANGEs.SingleOrDefault(x => x.SALARY_CODE == item.CODE);
                            if (mySalaryChangeDelete != null && mySalaryChangeDelete.CODE != string.Empty)
                            {
                                CommonGlobalVariable.globalDataContext.SALARY_CHANGEs.DeleteOnSubmit(mySalaryChangeDelete);//Đánh dấu xóa
                            }
                        }

                        CommonGlobalVariable.globalDataContext.SubmitChanges();//Xóa data

                        //Xóa thông tin tại table SALARY
                        foreach (SALARY item in myListSalaryDelete)
                        {
                            CommonGlobalVariable.globalDataContext.SALARies.DeleteOnSubmit(item);//Đánh dấu xóa
                        }
                        CommonGlobalVariable.globalDataContext.SubmitChanges();//Xóa data

                        return "Đã xóa thành công";
                    }
                    else
                    {
                        return "Không tìm thấy thông tin lương của nhân viên được chọn";
                    }
                }
            }
            catch (Exception ex)
            {
                CommonLogging.fsWriteLog(CommonConstants.LOG_TYPE_ERROR,
                           "SalaryCtrl.fsDeleteSalary Bắt đầu delete tiền lương",
                           CommonUtils.fsParamListToString(new object[3] { pIsFirst, pMonthToPay, strStaffCode }),
                           ex.ToString());
                return "Lỗi:\n" + ex.Message;
            }            
        }

        /// <summary>
        /// Tính toán lương tự động theo thông tin chấm công nhân viên
        /// </summary>
        /// <param name="pMonthToPay">Tháng tính lương</param>
        /// <param name="pStaffCode">Code nhân viên cần tính lương (nếu là string.empty thì sẽ tính toàn bộ nhân viên)</param>
        /// <returns></returns>
        public string fsCalcSalary(bool pIsFirst, DateTime pMonthToPay, string pStaffCode, string pOPID, DateTime pAddDate)
        {
            int nMidDay;
            DateTime dateFirstDayInMonth;
            DateTime dateLastDayInMonth;

            try//Tính toán các thông tin Init
            {
                //Lấy thời điểm tính lương
                MASTER myMaster = CommonGlobalVariable.globalDataContext.MASTERs.SingleOrDefault(x => x.GROUP_CODE == CommonConstants.NGAY_GIUA_THANG & x.DEL_FLG == false);
                if (myMaster == null)
                {
                    throw new Exception();
                }

                nMidDay = Convert.ToInt32(myMaster.VALUE);//Ngày giữa tháng            

                if (pIsFirst == true)
                {
                    //Ngày, giờ bắt đầu tháng
                    dateFirstDayInMonth = new DateTime(pMonthToPay.Year, pMonthToPay.Month, 1, 0, 0, 0);
                    //Ngày giờ kết thúc tháng
                    dateLastDayInMonth = new DateTime(pMonthToPay.Year, pMonthToPay.Month, nMidDay, 23, 59, 59);
                }
                else
                {
                    //Ngày, giờ giữa tháng
                    dateFirstDayInMonth = new DateTime(pMonthToPay.Year, pMonthToPay.Month, nMidDay + 1, 0, 0, 0);
                    //Ngày giờ kết thúc tháng
                    dateLastDayInMonth = new DateTime(pMonthToPay.Year, pMonthToPay.Month, DateTime.DaysInMonth(pMonthToPay.Year, pMonthToPay.Month), 23, 59, 59);
                }
            }
            catch (Exception ex)
            {
                CommonLogging.fsWriteLog(CommonConstants.LOG_TYPE_ERROR,
                           "SalaryCtrl.fsCalcSalary Tính toán các thông tin Init",
                           CommonUtils.fsParamListToString(new object[5] { pIsFirst, pMonthToPay, pStaffCode, pOPID, pAddDate }),
                           ex.ToString());
                return "Cài đặt ngày giữa tháng không đúng! Không thể tiến hành tính toán. Xin hãy kiểm tra lại.";
            }  

            /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
            
            try//Bắt đầu tính toán các thông tin lương
            {//Điều kiện trước khi tính lương: thông tin tính lương của tháng đó không được tồn tại.
                if (pStaffCode != string.Empty)//Tính lương cho từng nhân viên
                {
                    //Luồng tính lương:
                    //1. Kiểm tra thông tin lương cũ đã tồn tại hay chưa:
                    //  ->Nếu có: return trị NONE(thông báo tính không được, yêu cầu kiểm tra dữ liệu).
                    //  ->Nếu không: tiếp bước 2.
                    //2. Lấy thông tin nhân viên cần tính lương
                    //  ->Nếu không có thông tin hoặc nhân viên được setting là không tính lương (màn hình đăng ký nhân viên): return trị ERROR (không tính lương được).
                    //  ->Nếu có: tiếp bước 3.
                    //3. Lấy thông tổng số giờ làm việc của nhân viên từ table chấm công (HOURS_WORKED)
                    //  ->Nếu có làm việc (số giờ chấm công > 0): tiếp bước 4.
                    //  ->Nếu không có: Lưu thông tin chấm công với số tiền lương là 0 vào table SALARY. Đến bước 6.
                    //4. Tính lương, lương = số giờ làm việc * lương cơ bản.
                    //5. Lưu lại data vào table SALARY.
                    //6. Kết thúc

                    //Kiểm tra thông tin lương cũ có tồn tại hay không.
                    var checkExistSalaryInfo = CommonGlobalVariable.globalDataContext.SALARies.SingleOrDefault(x => x.STAFF_CODE == pStaffCode & x.MONTH_OUTPUT == pMonthToPay & x.IS_FIRST_PAY == pIsFirst);

                    if (checkExistSalaryInfo != null)
                    {
                        return "Nhân viên được chọn đã tính lương. Xin hãy xóa thông tin tính lương cũ và thực hiện lại thao tác.";//Không tính (yêu cầu xóa thông tin tính lương cũ)
                    }
                    else
                    {
                        //Lấy thông tin nhân viên cần tính lương
                        STAFF myStaffToCalcSalary = CommonGlobalVariable.globalDataContext.STAFFs.SingleOrDefault(x => x.CODE == pStaffCode);
                        
                        if (myStaffToCalcSalary.CODE == string.Empty || myStaffToCalcSalary.IS_SALARY_MANAGEMENT == false)//Không thấy thông tin nhân viên hoặc nhân viên được setting là không tính lương
                        {
                            return "Nhân viên được chọn không tồn tại hoặc đang được cài đặt là không tính lương. Xin hãy kiểm tra lại!";
                        }
                        else//Tìm thấy thông tin nhân viên
                        {        
                            //Lấy thông tin chấm công
                            List<HOURS_WORKED> myHoursWorkedList = CommonGlobalVariable.globalDataContext.HOURS_WORKEDs.Where(x=>x.STAFF_CODE == pStaffCode & x.CREATE_DATE >= dateFirstDayInMonth & x.CREATE_DATE <= dateLastDayInMonth).ToList();
                            
                            if (myHoursWorkedList != null && myHoursWorkedList.Count > 0)
                            {
                                //Có thông tin chấm công
                                //Tính toán lương
                                double nTotalTimeWorked = myHoursWorkedList.Sum(x => x.TIME_LENGHT);//Tổng số giờ làm việc trong tháng.
                                double nPayMoney = nTotalTimeWorked * myStaffToCalcSalary.UNIT_SALARY;//Tổng số lương tính được

                                //Save thông tin lương sau khi tính
                                SALARY mySalaryInsertData = new SALARY();
                                mySalaryInsertData.CODE = String.Format(CommonConstants.CODE_DATE, DateTime.Now);
                                mySalaryInsertData.STAFF_CODE = pStaffCode;
                                mySalaryInsertData.IS_FIRST_PAY = pIsFirst;
                                mySalaryInsertData.MONTH_OUTPUT = pMonthToPay;
                                mySalaryInsertData.TOTAL_TIME_WORKED = nTotalTimeWorked;
                                mySalaryInsertData.UNIT_SALARY = myStaffToCalcSalary.UNIT_SALARY;
                                mySalaryInsertData.PAY_SALARY = (long)nPayMoney;
                                mySalaryInsertData.TOTAL_PAY_SALARY = (long)nPayMoney;
                                mySalaryInsertData.IS_PAID = false;
                                mySalaryInsertData.PAY_DATE = DateTime.MaxValue;
                                mySalaryInsertData.OPID = pOPID;
                                mySalaryInsertData.ADD_DATE = pAddDate;
                                mySalaryInsertData.UPD_DATE = pAddDate;

                                CommonGlobalVariable.globalDataContext.SALARies.InsertOnSubmit(mySalaryInsertData);
                                CommonGlobalVariable.globalDataContext.SubmitChanges();

                                return "Tiền lương nhân viên đã được tính toán xong.";//Tính lương thành công
                            }
                            else
                            {
                                //Không có thông tin chấm công
                                //Lưu thông tin với lương = 0
                                SALARY mySalaryInsertData = new SALARY();
                                mySalaryInsertData.CODE = String.Format(CommonConstants.CODE_DATE, DateTime.Now);
                                mySalaryInsertData.STAFF_CODE = pStaffCode;
                                mySalaryInsertData.IS_FIRST_PAY = pIsFirst;
                                mySalaryInsertData.MONTH_OUTPUT = pMonthToPay;
                                mySalaryInsertData.TOTAL_TIME_WORKED = 0;
                                mySalaryInsertData.UNIT_SALARY = myStaffToCalcSalary.UNIT_SALARY;
                                mySalaryInsertData.PAY_SALARY = 0;
                                mySalaryInsertData.TOTAL_PAY_SALARY = 0;
                                mySalaryInsertData.IS_PAID = false;
                                mySalaryInsertData.PAY_DATE = DateTime.MaxValue;
                                mySalaryInsertData.OPID = pOPID;
                                mySalaryInsertData.ADD_DATE = pAddDate;
                                mySalaryInsertData.UPD_DATE = pAddDate;

                                CommonGlobalVariable.globalDataContext.SALARies.InsertOnSubmit(mySalaryInsertData);
                                CommonGlobalVariable.globalDataContext.SubmitChanges();//Save data

                                return "Tiền lương nhân viên đã được tính toán xong.\nNhân viên này trong tháng không có làm việc.";//Tính lương xong
                            }                                    
                        }
                    }
                }
                else//Tính lương cho tất cả nhân viên
                {
                    //Luồng tính lương:
                    //1. Lấy thông tin của tất cả nhân viên cần tính lương
                    //2. Kiểm tra thông tin tính lương đã tồn tại chưa
                    //  ->Nếu có: thông báo lỗi, return.
                    //  ->Nếu không: tiếp bước 3.
                    //3. Bắt đầu tính lương cho từng nhân viên. Bắt đầu vòng lặp
                    //4. Lấy thông tin chấm công
                    //  ->Nếu có: tính lương = tổng số giờ công * tiền lương cơ bản.
                    //  ->Nếu không: lương = 0.
                    //5. Insert data
                    //6. Kết thúc vòng lặp
                    //7. Save thông tin và return.

                    //Load thông tin của tất cả nhân viên cần tính lương (loại trừ các nhân viên được setting là không tính.
                    List<STAFF> myStaffListToCalcSalary = CommonGlobalVariable.globalDataContext.STAFFs.Where(x => x.IS_SALARY_MANAGEMENT == true).ToList();

                    //Kiểm tra thông tin tính lương cũ đã tồn tại hay chưa.
                    foreach (var staff in myStaffListToCalcSalary)
                    {
                        var salary = CommonGlobalVariable.globalDataContext.SALARies.SingleOrDefault(x => x.STAFF_CODE == staff.CODE & x.MONTH_OUTPUT == pMonthToPay & x.IS_FIRST_PAY == pIsFirst);
                        if (salary != null)
                        {
                            return "Một số nhân viên đã được tính lương. Xin hãy xóa các thông tin tính lương và thực hiện lại thao tác.";
                        }
                    }

                    //Kiểm bắt đầu tính lương cho từng nhân viên
                    long nUniqueCode = Convert.ToInt64(String.Format(CommonConstants.CODE_DATE, DateTime.Now));//Key code của table (vì lấy thông tin theo ngày giờ, tính nhanh quá sẽ bị trùng khóa chính).
                    foreach (var staff in myStaffListToCalcSalary)
                    {      
                        //Lấy thông tin chấm công của từng nhân viên
                        List<HOURS_WORKED> myHoursWorkedList = CommonGlobalVariable.globalDataContext.HOURS_WORKEDs.Where(x => x.STAFF_CODE == staff.CODE & x.CREATE_DATE >= dateFirstDayInMonth & x.CREATE_DATE <= dateLastDayInMonth).ToList();

                        if (myHoursWorkedList != null && myHoursWorkedList.Count > 0)
                        {
                            //Nếu có thông tin chấm công
                            //Tính toán lương
                            double nTotalTimeWorked = myHoursWorkedList.Sum(x => x.TIME_LENGHT);//Tổng số giờ làm việc trong tháng.
                            double nPayMoney = nTotalTimeWorked * staff.UNIT_SALARY;//Tổng số lương tính được

                            //Save thông tin lương sau khi tính
                            SALARY mySalaryInsertData = new SALARY();
                            mySalaryInsertData.CODE = (++nUniqueCode).ToString(); 
                            mySalaryInsertData.STAFF_CODE = staff.CODE;
                            mySalaryInsertData.IS_FIRST_PAY = pIsFirst;
                            mySalaryInsertData.MONTH_OUTPUT = pMonthToPay;
                            mySalaryInsertData.TOTAL_TIME_WORKED = nTotalTimeWorked;
                            mySalaryInsertData.UNIT_SALARY = staff.UNIT_SALARY;
                            mySalaryInsertData.PAY_SALARY = (long)nPayMoney;
                            mySalaryInsertData.TOTAL_PAY_SALARY = (long)nPayMoney;
                            mySalaryInsertData.IS_PAID = false;
                            mySalaryInsertData.PAY_DATE = DateTime.MaxValue;
                            mySalaryInsertData.OPID = pOPID;
                            mySalaryInsertData.ADD_DATE = pAddDate;
                            mySalaryInsertData.UPD_DATE = pAddDate;

                            CommonGlobalVariable.globalDataContext.SALARies.InsertOnSubmit(mySalaryInsertData);
                        }
                        else
                        {
                            //Nếu không có thông tin chấm công
                            //Lưu thông tin lương với số tiền = 0
                            SALARY mySalaryInsertData = new SALARY();
                            mySalaryInsertData.CODE = (++nUniqueCode).ToString();
                            mySalaryInsertData.STAFF_CODE = staff.CODE;
                            mySalaryInsertData.IS_FIRST_PAY = pIsFirst;
                            mySalaryInsertData.MONTH_OUTPUT = pMonthToPay;
                            mySalaryInsertData.TOTAL_TIME_WORKED = 0;
                            mySalaryInsertData.UNIT_SALARY = staff.UNIT_SALARY;
                            mySalaryInsertData.PAY_SALARY = 0;
                            mySalaryInsertData.TOTAL_PAY_SALARY = 0;
                            mySalaryInsertData.IS_PAID = false;
                            mySalaryInsertData.PAY_DATE = DateTime.MaxValue;
                            mySalaryInsertData.OPID = pOPID;
                            mySalaryInsertData.ADD_DATE = pAddDate;
                            mySalaryInsertData.UPD_DATE = pAddDate;

                            CommonGlobalVariable.globalDataContext.SALARies.InsertOnSubmit(mySalaryInsertData);
                        }
                    }
                   
                    CommonGlobalVariable.globalDataContext.SubmitChanges();//Save data
                    return "Tiền lương nhân viên đã được tính toán xong.";
                }
            }
            catch (Exception ex)
            {
                CommonLogging.fsWriteLog(CommonConstants.LOG_TYPE_ERROR,
                           "SalaryCtrl.fsCalcSalary Bắt đầu tính toán các thông tin lương",
                           CommonUtils.fsParamListToString(new object[5] { pIsFirst, pMonthToPay, pStaffCode, pOPID, pAddDate }),
                           ex.ToString());
                return "Lỗi thực thi:\n" + ex.Message;
            }            
        }

        /// <summary>
        /// Load thông tin lương của nhân viên
        /// </summary>
        /// <param name="pStaffCode">Code nhân viên (nếu load tất cả nhan viên thì sẽ input string.empty)</param>
        /// <param name="pMonthPay">Tháng tính lương</param>
        /// <returns></returns>
        public List<VIEW_Salary> fsLoadSalaryList(string pStaffCode, bool pIsFirstPay, DateTime pMonthPay)
        {
            try
            {
                List<VIEW_Salary> myListSalary = null;
                //Ngày, giờ bắt đầu tháng
                DateTime dateFirstDayInMonth = new DateTime(pMonthPay.Year, pMonthPay.Month, 1, 0, 0, 0);
                //Ngày giờ kết thúc tháng
                DateTime dateLastDayInMonth = new DateTime(pMonthPay.Year, pMonthPay.Month, DateTime.DaysInMonth(pMonthPay.Year, pMonthPay.Month), 23, 59, 59);


                if (pStaffCode != string.Empty)
                {
                    //myListSalary = CommonGlobalVariable.globalDataContext.SALARies.Where(x => x.STAFF_CODE == pStaffCode & x.MONTH_OUTPUT >= dateFirstDayInMonth & x.MONTH_OUTPUT <= dateLastDayInMonth).ToList();
                    myListSalary = (from slr in CommonGlobalVariable.globalDataContext.SALARies
                                    where slr.STAFF_CODE == pStaffCode
                                        & slr.STAFF.DEL_FLG == false
                                        & slr.MONTH_OUTPUT >= dateFirstDayInMonth & slr.MONTH_OUTPUT <= dateLastDayInMonth
                                        & slr.IS_FIRST_PAY == pIsFirstPay                                        
                                    select new VIEW_Salary
                                    {
                                        strSALARY_CODE = slr.CODE,                                                                              //Key code
                                        strSTAFF_CODE = slr.STAFF_CODE,                                                                         //Code nhân viên
                                        strSTAFF_NAME = slr.STAFF.NAME,                                                                         //Code nhân viên
                                        bIS_FRIST_PAY = slr.IS_FIRST_PAY,                                                                         //Code kỳ tính lương
                                        strFRIST_PAY = slr.IS_FIRST_PAY == true ? "Đầu tháng" : "Cuối tháng",                                    //Tên kỳ tính lương
                                        dateMONTH_OUTPUT = slr.MONTH_OUTPUT,                                                                    //Tháng/năm tính lương
                                        iTOTAL_TIME_WORKDED = slr.TOTAL_TIME_WORKED,                                                            //Số giờ làm việc trong tháng
                                        iUNIT_SALARY = slr.UNIT_SALARY,                                                                         //Lương đơn vị
                                        iPAY_SALARY = slr.PAY_SALARY,                                                                           //Số tiền lương (tính theo giờ công)
                                        iTOTAL_PAY_SALARY = slr.TOTAL_PAY_SALARY,                                                               //Số tiền lương phải trả (đã có điều chỉnh)
                                        bIS_PAID = slr.IS_PAID,                                                                                 //Đã chi trả lương hay chưa
                                        datePAY_DATE = slr.PAY_DATE,                                                                            //Ngày chi trả lương
                                        strSALARY_CHANGE_CODE = slr.SALARY_CHANGEs.SingleOrDefault(x => x.SALARY_CODE == slr.CODE).CODE,        //Key code
                                        nSALARY_CHANGE_AMOUNT = slr.SALARY_CHANGEs.SingleOrDefault(x => x.SALARY_CODE == slr.CODE).AMOUNT,      //Số tiền lương thay đổi
                                        strSALARY_CHANGE_NOTE = slr.SALARY_CHANGEs.SingleOrDefault(x => x.SALARY_CODE == slr.CODE).NOTE         //Ghi chú về thay đổi lương
                                    }).OrderBy(x => x.strSTAFF_NAME).ToList();
 
                }
                else
                {
                    //myListSalary = CommonGlobalVariable.globalDataContext.SALARies.Where(x => x.MONTH_OUTPUT >= dateFirstDayInMonth & x.MONTH_OUTPUT <= dateLastDayInMonth).ToList();
                    myListSalary = (from slr in CommonGlobalVariable.globalDataContext.SALARies
                                    where slr.MONTH_OUTPUT >= dateFirstDayInMonth & slr.MONTH_OUTPUT <= dateLastDayInMonth
                                       && slr.STAFF.DEL_FLG == false
                                       && slr.IS_FIRST_PAY == pIsFirstPay
                                    select new VIEW_Salary
                                    {
                                        strSALARY_CODE = slr.CODE,                                                                              //Key code
                                        strSTAFF_CODE = slr.STAFF_CODE,                                                                         //Code nhân viên
                                        strSTAFF_NAME = slr.STAFF.NAME,                                                                         //Code nhân viên
                                        bIS_FRIST_PAY = slr.IS_FIRST_PAY,                                                                         //Code kỳ tính lương
                                        strFRIST_PAY = slr.IS_FIRST_PAY == true ? "Đầu tháng" : "Cuối tháng",                                    //Tên kỳ tính lương
                                        dateMONTH_OUTPUT = slr.MONTH_OUTPUT,                                                                    //Tháng/năm tính lương
                                        iTOTAL_TIME_WORKDED = slr.TOTAL_TIME_WORKED,                                                            //Số giờ làm việc trong tháng
                                        iUNIT_SALARY = slr.UNIT_SALARY,                                                                         //Lương đơn vị
                                        iPAY_SALARY = slr.PAY_SALARY,                                                                           //Số tiền lương (tính theo giờ công)
                                        iTOTAL_PAY_SALARY = slr.TOTAL_PAY_SALARY,                                                               //Số tiền lương phải trả (đã có điều chỉnh)
                                        bIS_PAID = slr.IS_PAID,                                                                                 //Đã chi trả lương hay chưa
                                        datePAY_DATE = slr.PAY_DATE,                                                                            //Ngày chi trả lương
                                        strSALARY_CHANGE_CODE = slr.SALARY_CHANGEs.SingleOrDefault(x => x.SALARY_CODE == slr.CODE).CODE,        //Key code
                                        nSALARY_CHANGE_AMOUNT = slr.SALARY_CHANGEs.SingleOrDefault(x => x.SALARY_CODE == slr.CODE).AMOUNT,      //Số tiền lương thay đổi
                                        strSALARY_CHANGE_NOTE = slr.SALARY_CHANGEs.SingleOrDefault(x => x.SALARY_CODE == slr.CODE).NOTE         //Ghi chú về thay đổi lương
                                    }).OrderBy(x => x.strSTAFF_NAME).ToList();
                }

                return myListSalary;
            }
            catch (Exception ex)
            {
                CommonLogging.fsWriteLog(CommonConstants.LOG_TYPE_ERROR,
                           "SalaryCtrl.fsLoadSalaryList",
                           CommonUtils.fsParamListToString(new object[3] { pStaffCode, pIsFirstPay, pMonthPay }),
                           ex.ToString());
                return null;
            }
        }

        /// <summary>
        /// Update thông tin table SALARY, SALARY_CHANGE
        /// </summary>
        /// <param name="pSalaryCode">Key code SALARY</param>
        /// <param name="pSalaryChangeCode">Key code SALARY_CHANGE</param>
        /// <param name="pSalaryChangeAmount">Số tiền thay đổi</param>
        /// <param name="pSalaryChangeNote">Ghi chú</param>
        /// <param name="pIsPaid">Đã chi trả lương thay chưa (true = rồi, false = chưa)</param>
        /// <param name="pPayDate">Ngày chi trả</param>
        /// <returns></returns>
        public ResultStatus fsUpdateSalary(string pSalaryCode, string pSalaryChangeCode, long pSalaryChangeAmount, string pSalaryChangeNote, bool pIsPaid, DateTime pPayDate, string pOPID, DateTime pAddDate)
        {
            try
            {               
                SALARY mySalary = null;
                SALARY_CHANGE mySalaryChange = null;

                //Cập nhật table SALARY_CHANGE
                mySalaryChange = CommonGlobalVariable.globalDataContext.SALARY_CHANGEs.SingleOrDefault(x => x.CODE == pSalaryChangeCode);

                if (mySalaryChange == null)//Thêm mới
                {
                    if (pSalaryChangeAmount != 0 || pSalaryChangeNote != string.Empty)
                    {
                        mySalaryChange = new SALARY_CHANGE();
                        mySalaryChange.CODE = String.Format(CommonConstants.CODE_DATE, DateTime.Now);
                        mySalaryChange.SALARY_CODE = pSalaryCode;
                        mySalaryChange.AMOUNT = pSalaryChangeAmount;
                        mySalaryChange.NOTE = pSalaryChangeNote;
                        mySalaryChange.OPID = pOPID;
                        mySalaryChange.ADD_DATE = pAddDate;
                        mySalaryChange.UPD_DATE = pAddDate;

                        CommonGlobalVariable.globalDataContext.SALARY_CHANGEs.InsertOnSubmit(mySalaryChange);
                        CommonGlobalVariable.globalDataContext.SubmitChanges();
                    }
                }
                else//Cập nhật
                {
                    mySalaryChange.AMOUNT = pSalaryChangeAmount;
                    mySalaryChange.NOTE = pSalaryChangeNote;
                    mySalaryChange.OPID = pOPID;
                    mySalaryChange.UPD_DATE = pAddDate;

                    CommonGlobalVariable.globalDataContext.SubmitChanges();
                }

                //Cập nhật table SALARY
                mySalary = CommonGlobalVariable.globalDataContext.SALARies.SingleOrDefault(x => x.CODE == pSalaryCode);

                if (mySalary.CODE != null)
                {
                    mySalary.IS_PAID = pIsPaid;
                    mySalary.PAY_DATE = pPayDate;
                    mySalary.TOTAL_PAY_SALARY = (long)((mySalary.TOTAL_TIME_WORKED * mySalary.UNIT_SALARY) + pSalaryChangeAmount);
                    mySalary.OPID = pOPID;
                    mySalary.UPD_DATE = pAddDate;

                    CommonGlobalVariable.globalDataContext.SubmitChanges();
                }
                else
                {
                    return ResultStatus.ERROR;
                }

                return ResultStatus.SUCCESS;
            }
            catch (Exception ex)
            {
                CommonLogging.fsWriteLog(CommonConstants.LOG_TYPE_ERROR,
                           "SalaryCtrl.fsUpdateSalary",
                           CommonUtils.fsParamListToString(new object[8] { pSalaryCode, pSalaryChangeCode, pSalaryChangeAmount, pSalaryChangeNote, pIsPaid, pPayDate, pOPID, pAddDate }),
                           ex.ToString());
                return ResultStatus.ERROR;
            }            
        }
    }
}
